<?php    
    use SharedPHP\UnitConverter;
        
    class TemplateControl extends Control {
        protected static $_callable = array(
            "delete",
            "load",
            "save",
            "search"
        );
        
        /**
         * Funktio poistaa harjoituspohjan tiedot tietokannasta.
         *
         * @return bool
         */
        public static function delete($data) {
            $result = false;
            
            DB::begin();
            
            try {
                $template = new TemplateModel(array(
                    "hashid" => arrGet($data,"hashid")
                ));
                
                # Tarkasta onko harjoituspohja liitetty harjoituksiin
                $query = DB::preparedQuery("
                    SELECT id
                    FROM workout
                    WHERE templateid=:templateid
                    LIMIT 1
                ",array(
                    "templateid" => $template->id
                ));
                if (DB::numRows($query) == 1) {
                    DB::freeResult($query);
                    throw new DBException(
                        "Template is attached to one or more workouts",
                        40,
                        __CLASS__,
                        "Template is attached to one or more workouts"
                    );
                }
                
                # Tarkasta onko harjoituspohja liitetty harjoitusohjelmiin
                $query = DB::preparedQuery("
                    SELECT id
                    FROM training_program_template_link
                    WHERE templateid=:templateid
                    LIMIT 1
                ",array(
                    "templateid" => $template->id
                ));
                if (DB::numRows($query) == 1) {
                    DB::freeResult($query);
                    throw new DBException(
                        "Template is attached to one or more training programs",
                        40,
                        __CLASS__,
                        "Template is attached to one or more training programs"
                    );
                }
                
                $template->delete();
                
                $result = true;
            } catch (Exception $e) {
                DB::rollback();
                throw $e;
            }
            
            DB::commit();
            
            return $result;
        }
        
        /**
         * Funktio hakee harjoituspohjan tiedot tietokannasta.
         *
         * @return  array
         */
        public static function load($data) {
            $result = array();
            
            $template = new TemplateModel(array(
                "hashid" => arrGet($data,"hashid")
            ));
            
            # Harjoituspohjan perustiedot
            $result["hashid"]           = $template->hashid;
            $result["extratext"]        = $template->extratext;
            $result["updated"]          = $template->updated;
            $result["rowstamp"]         = $template->rowstamp;
            
            # Harjoitteet
            $cache = array();
            $result["exercises"] = array();
            foreach ((array)$template->template_exercise as $exercise) {
                # Toistot
                $sets = array();                
                foreach ((array)$exercise->template_exercise_set as $set) {
                    # Löytyykö cachesta
                    if (!isset($cache[$set->exerciseid])) {
                        $cache[$set->exerciseid] = new ExerciseModel($set->exerciseid);
                    }
                    
                    $sets[] = array(
                        "exerciseid"        => $set->exerciseid,
                        "exercisetext"      => $cache[$set->exerciseid]->exercise,
                        "category"          => $cache[$set->exerciseid]->category,
                        "musclegroup"       => $cache[$set->exerciseid]->musclegroup,
                        "repetitions"       => $set->repetitions,
                        "repetitions_end"   => $set->repetitions_end,
                        "weight"            => (($exercise->unit == "kg") ? $set->weight_kg : $set->weight_lb),
                        "weight_kg"         => $set->weight_kg,
                        "weight_lb"         => $set->weight_lb,
                        "onerepmax_percent" => $set->onerepmax_percent,
                        "repetitions_type"  => $set->repetitions_type,
                        "barbell_type"      => $set->barbell_type,
                        "rest_interval_sec" => $set->rest_interval_sec
                    );
                }
                
                $result["exercises"][] = array(
                    "unit"              => $exercise->unit,
                    "extratext"         => $exercise->extratext,
                    "special"           => $exercise->special,
                    "gear_belt"         => $exercise->gear_belt,
                    "gear_knee_wraps"   => $exercise->gear_knee_wraps,
                    "gear_shirt"        => $exercise->gear_shirt,
                    "gear_suit"         => $exercise->gear_suit,
                    "gear_wrist_straps" => $exercise->gear_wrist_straps,
                    "gear_wrist_wraps"  => $exercise->gear_wrist_wraps,
                    "sets"              => $sets
                );
            }
            
            # Merkinnät
            $result["records"] = array();
            foreach ((array)$template->template_record as $record) {
                $result["records"][] = array(
                    "record" => $record->record
                );
            }
            
            return $result;
        }
        
        /**
         * Tallentaa harjoituspohjan tiedot ja palauttaa pohjan hashid:n.
         *
         * @param   array   $data   Tiedot
         * @return  string
         */
        public static function save($data) {
            DB::begin();
            
            try {
                $arr = null;
                $hashid = arrGet($data,"hashid");
                if (isset($hashid)) {
                    $arr = array("hashid" => $hashid);
                }
                
                $template = new TemplateModel($arr);
                
                # Aseta userid jos luodaan uutta
                if (!isset($hashid)) {
                    $template->userid       = LoginControl::get("userid");
                    $template->from_userid  = LoginControl::get("userid");
                    $template->accepted     = date("Y-m-d H:i:s");
                } else {
                    # Poista muokkauksen yhteydessa vanhat alitietueet
                    $template->deleteChilds();
                    $template->unsetChilds();
                    
                    # Aseta päivitysaika
                    $template->updated = date("Y-m-d H:i:s");
                }
                
                $template->extratext = $data;
                
                # Harjoitteet
                $c = 0;
                $cache = array();
                foreach ((array)arrGet($data,"exercises") as $exercise) {
                    RequestHandler::addIteration("TemplateExerciseModel");
                    
                    $exrcs = new TemplateExerciseModel();                    
                    $exrcs->unit                = $exercise;
                    $exrcs->extratext           = $exercise;
                    $exrcs->gear_belt           = $exercise;
                    $exrcs->gear_knee_wraps     = $exercise;
                    $exrcs->gear_shirt          = $exercise;
                    $exrcs->gear_suit           = $exercise;
                    $exrcs->gear_wrist_straps   = $exercise;
                    $exrcs->gear_wrist_wraps    = $exercise;
                    
                    $special = arrGet($exercise,"special","");
                    if (mb_strlen($special) > 0) {
                        $exrcs->special = $special;
                    }
                    
                    # Toistot
                    $c2 = 0;
                    foreach ((array)arrGet($exercise,"sets") as $set) {
                        RequestHandler::addIteration("TemplateExerciseSetModel");
                        
                        # Löytyykö cachesta
                        $exerciseid = arrGet($set,"exerciseid");
                        if ($exerciseid && !isset($cache[$exerciseid])) {
                            $cache[$exerciseid] = (new ExerciseModel($exerciseid))->id;
                        } 
                        
                        $exerciseset = new TemplateExerciseSetModel();
                        $exerciseset->exerciseid        = $exerciseid;
                        $exerciseset->repetitions       = $set;
                        $exerciseset->repetitions_type  = $set;
                        
                        $weightKg   = arrGet($set,"weight_kg","");
                        $weightLb   = arrGet($set,"weight_lb","");
                        $weight     = arrGet($set,"weight","");
                        if (mb_strlen($weight) > 0) {
                            # Muunna yksiköt
                            switch ($exrcs->unit) {
                                case "kg":
                                    $weightKg = $weight;
                                    $weightLb = round(UnitConverter::kgToLb($weight),2);
                                    break;
                                
                                case "lb":
                                    $weightKg = round(UnitConverter::lbToKg($weight),2);
                                    $weightLb = $weight;
                                    break;
                            }
                        }
                        
                        # Tallennetaan käyttäjän käyttämä painoyksikkö ensin
                        switch ($exrcs->unit) {
                            case "kg":
                                $exerciseset->weight_kg = $weightKg;
                                $exerciseset->weight_lb = $weightLb;
                                break;
                            
                            case "lb":
                                $exerciseset->weight_lb = $weightLb;
                                $exerciseset->weight_kg = $weightKg;
                                break;
                        }
                        
                        # Toistovälin loppu
                        $repEnd = arrGet($set,"repetitions_end","");
                        if (mb_strlen($repEnd) > 0) {
                            $exerciseset->repetitions_end = $repEnd;
                        }
                        
                        # Yhden toiston maksimi
                        $oneRepMaxP = arrGet($set,"onerepmax_percent","");
                        if (mb_strlen($oneRepMaxP) > 0) {
                            $exerciseset->onerepmax_percent = $oneRepMaxP;
                        }
                        
                        # Levytangon tyyppi
                        $barbellType = arrGet($set,"barbell_type","");
                        if (mb_strlen($barbellType) > 0) {
                            $exerciseset->barbell_type = $barbellType;
                        }
                        
                        # Lepotauko
                        $rest = arrGet($set,"rest_interval_sec","");
                        if (mb_strlen($rest) > 0) {
                            $exerciseset->rest_interval_sec = $rest;
                        }
                        
                        $exrcs->template_exercise_set = $exerciseset;
                        
                        if (++$c2 >= 100) {
                            break;
                        }
                    }
                    RequestHandler::clearIteration("TemplateExerciseSetModel");
                    
                    $template->template_exercise = $exrcs;
                    
                    if (++$c >= 100) {
                        break;
                    }
                }
                RequestHandler::clearIteration("TemplateExerciseModel");
                
                # Merkinnät
                $c = 0;
                foreach ((array)arrGet($data,"records") as $record) {
                    RequestHandler::addIteration("TemplateRecordModel");
                    if (mb_strlen(arrGet($record,"record","")) > 0) {
                        $rcd = new TemplateRecordModel();
                        $rcd->record = $record;
                        
                        $template->template_record = $rcd;
                        
                        if (++$c >= 100) {
                            break;
                        }
                    }
                }
                RequestHandler::clearIteration("TemplateRecordModel");
                                  
                $template->write();
                $hashid = $template->hashid;
            } catch (Exception $e) {
                DB::rollback();
                throw $e;
            }
            
            DB::commit();
            
            return $hashid;
        }
        
        /**
         * Etsii harjoituspohjia tietokannasta (maksimissaan 10 000 kpl).
         *
         * @param   array   $data   Hakuparametrit
         * @return  array
         */
        public static function search($data) {
            $result = array(                
                "list"          => array(),
                "totalCount"    => 0
            );            
            
            $params = array(
                "userid" => LoginControl::get("userid")
            );
            $where = "";
            
            # Harjoitteen id
            if (isset($data["exerciseid"]) && $data["exerciseid"]) {
                $params["exerciseid"] = $data["exerciseid"];
                $where .= " AND exercise.id IN (:exerciseid)";
            }
            
            # Harjoitteen lihasryhmä
            if (isset($data["musclegroup"]) && $data["musclegroup"]) {
                $params["musclegroup"] = $data["musclegroup"];
                $where .= " AND exercise.musclegroup IN (:musclegroup)";
            }
            
            # Positio ja haettavien rivien määrä
            $pos = 0;
            $count = null;
            if (isset($data["pos"]) && (int)$data["pos"] >= 0) {
                $pos = (int)$data["pos"]; 
            }
            if (isset($data["count"])) {
                $count = (int)$data["count"];
                if ($count <= 0) {
                    return $result;
                }
            }
            
            # Suorita haku
            $query = DB::preparedQuery("
                SELECT template.hashid,
                  template.extratext,
                  COUNT(DISTINCT template_exercise.id) AS exercises,
                  COUNT(template_exercise_set.id) AS sets,
                  SUM(
                    IF(
                        template_exercise_set.repetitions_end IS NOT NULL,
                        template_exercise_set.repetitions_end,
                        template_exercise_set.repetitions
                    )
                  ) AS repetitions
                FROM template
                LEFT JOIN template_exercise ON template_exercise.templateid = template.id
                LEFT JOIN template_exercise_set ON template_exercise_set.template_exerciseid = template_exercise.id
                LEFT JOIN exercise ON exercise.id = template_exercise_set.exerciseid
                WHERE template.userid=:userid{$where}
                GROUP BY template.id
                ORDER BY template.extratext,template.id
                LIMIT 10000
                ",$params
            );
            $numrows = DB::numRows($query);
            if ($numrows > 0) {
                if (!isset($count)) {
                    $count = $numrows-$pos;
                }
                
                if ($count > 0) {
                    if ($pos > 0) {
                        DB::dataSeek($query,$pos);
                    }
                    
                    $c = 0;
                    while ($row = DB::fetchAssoc($query)) {
                        $result["list"][] = $row;
                        if (++$c >= $count) {
                            break;
                        }
                    }
                }
                DB::freeResult($query);
                
                $result["totalCount"] = $numrows;
            }
            
            return $result;
        }
    }